<?php

namespace addons\groupon\controller;

use addons\groupon\model\UserSalespersonApplyModel;
use addons\groupon\validate\store\Apply;
use app\admin\model\groupon\water\Card;
use app\common\library\Ems;
use app\common\library\Sms;
use app\common\model\ScoreLog;
use app\common\model\ScoreOrderLog;
use fast\Random;
use think\Validate;
use addons\groupon\library\Wechat;
use think\Db;
use addons\groupon\model\UserOauth;
use addons\groupon\model\User as UserModel;
use addons\groupon\model\UserStore;
/**
 * 会员接口
 */
class User extends Base
{
    protected $noNeedLogin = [
        'login',
        'mobilelogin',
        'accountLogin',
        'register',
        'resetpwd',
        'changeemail',
        'changemobile',
        'third',
        'wxMiniProgramOauth',
        'getWxMiniProgramSessionKey',
        'getUserDefaultFields',
        'send_points'
    ];
    protected $noNeedRight = '*';

    public function _initialize()
    {
        return parent::_initialize();
    }

    public function send_points()
    {
        $order_num = input('post.order_num');
        $num       = input('post.num', 0);
        $pay_type  = input('post.pay_type');
        if (!$order_num || !$num || !in_array($pay_type, [1, 2, 3])) {
            $this->error('参数错误');
        }
        $mobile = input('post.mobile');
        if (!Validate::regex($mobile, "^1\d{10}$")) {
            $this->error(__('手机号格式不正确'));
        }
        $money = input('post.money', 0);
        if ($money < 0) {
            $this->error('金额不正确');
        }
        $goods_id = input('goods_id');
        if (!$goods_id) {
            $this->error('缺少商品ID');
        }
        $inser_arr['order_num']  = $order_num;
        $inser_arr['mobile']     = $mobile;
        $inser_arr['goods_id']   = $goods_id;
        $inser_arr['num']        = $num;
        $inser_arr['money']      = $money;
        $inser_arr['pay_type']   = $pay_type;
        $inser_arr['createtime'] = date("Y-m-d H:i:s");
        $inser_arr['send_json']  = json_encode(input('post.'), true);
        db('groupon_goods_send')->insert($inser_arr);
        $this->success('操作成功');
    }

    /**
     * @menu:获取水卡
     */
    public function user_card_info(){
        $mobile = input('mobile');
        $userInfo = \addons\groupon\model\User::where(['mobile'=>$mobile])->find();
        $card  = 0;
        if($userInfo){
            $card = $userInfo['water_card'];
        }
        $this->success('ok',['card'=>$card]);
    }


    /**
     * 会员中心
     */
    public function index()
    {
        $auth = \app\common\library\Auth::instance();
        $auth->setAllowFields([
            'id',
            'username',
            'nickname',
            'mobile',
            'avatar',
            'score',
            'birthday',
            'money',
            'group',
            'group_id',
            'child_user_count',
            'child_user_count_1',
            'child_user_count_2',
            'total_consume',
            'is_salesperson'
        ]);
        $data           = $auth->getUserinfo();
        $data['avatar'] = $data['avatar'] ? cdnurl($data['avatar'], true) : '';
        if (!isset($data['group'])) {
            $data['group'] = \addons\groupon\model\UserGroup::get($data['group_id']);
        }

        // 查询用户优惠券数量
        $userCoupons         = \addons\groupon\model\Coupons::getCouponsList(1);
        $data['coupons_num'] = count($userCoupons);

        // 查询用户是否是自提点管理员
        $userStores       = UserStore::where('user_id', $data['id'])->select();
        $data['is_store'] = $userStores ? 1 : 0;
        $data['store_id'] = 0;
        if (count($userStores) == 1) {
            // 只有一个店铺 直接进入店铺
            $data['store_id'] = $userStores[0]['store_id'];
        }
//        $data['score'] += ScoreOrderLog::where(['user_id' => $this->auth->id, 'status' => 1])->sum('score');
        $this->success('用户信息', $data);
    }

    /**
     * 会员登录
     *
     * @param  string  $account  账号
     * @param  string  $password  密码
     */
    public function accountLogin()
    {
        $account  = $this->request->post('account');
        $password = $this->request->post('password');
        if (!$account || !$password) {
            $this->error(__('Invalid parameters'));
        }
        $ret = $this->auth->login($account, $password);
        if ($ret) {
            $data = ['userinfo' => $this->auth->getUserinfo()];
            $this->success(__('Logged in successful'), $data);
        } else {
            $this->error($this->auth->getError());
        }
    }

    /**
     * 获取微信小程序session_key
     *
     * @param  string  $code  加密code
     * @param  boolean  $autoLogin  是否自动登录(需已注册会员)
     */
    public function getWxMiniProgramSessionKey()
    {
        $post           = $this->request->post();
        $autoLogin      = $post['autoLogin'];
        $wechat         = new Wechat('wxMiniProgram');
        $decryptSession = $wechat->code($post['code']);
        if (!isset($decryptSession['session_key'])) {
            $this->error('未获取session_key,请重启应用');
        }
        $uuid = Random::uuid();
        \think\Cache::set($uuid, $decryptSession, 24 * 3600 * 30); // 强制30天过期
        $userOauth = UserOauth::get([
            'provider' => 'Wechat',
            'platform' => 'wxMiniProgram',
            'openid'   => $decryptSession['openid'],
            'user_id'  => ['neq', 0]
        ]);
        if ($userOauth) {
            $userOauth->save(['session_key' => $decryptSession['session_key']]);
        }
        if ($autoLogin && $userOauth) {
            $ret = $this->auth->direct($userOauth->user_id);
            if ($ret) {
                $token = $this->auth->getToken();
                $this->success(__('Logged in successful'),
                    ['token' => $token, 'session_id' => $uuid, 'openid' => $decryptSession['openid']]);
            } else {
                $this->error($this->auth->getError());
            }
        }

        $this->success('', ['session_id' => $uuid]);
    }

    /**
     * 微信小程序登录
     *
     * @param  string  $session_key  session_key
     * @param  string  $signature  校验签名
     * @param  string  $iv  解密向量
     * @param  string  $encryptedData  需解密完整用户信息
     * @param  boolean  $refresh  重新获取或刷新最新的用户信息 (用户头像失效或微信客户端修改昵称等情况)
     */
    public function wxMiniProgramOauth()
    {
        $post                  = $this->request->post();
        $post['encryptedData'] = $this->request->post('encryptedData', null, null);

        $token = Db::transaction(function () use ($post) {
            try {
                $wechat         = new Wechat('wxMiniProgram');
                $decryptSession = \think\Cache::get($post['session_id']);
                if (!$decryptSession || !isset($decryptSession['openid'])) {
                    throw new \Exception('未获取到登录态,请重试');
                }
                $decryptUserInfo = $wechat->decryptData($decryptSession['session_key'], $post['iv'],
                    $post['encryptedData']); // 客户端传值数据都不可信，需服务端解密用户信息
                $decryptUserInfo = array_merge($decryptUserInfo, $decryptSession);
                //组装decryptData
                $decryptData = array_change_key_case($decryptUserInfo, CASE_LOWER);
                if (empty($decryptData['openid'])) {
                    throw new \Exception('code错误,请重试');
                }
                $mobile = '';
                if (!empty($decryptData['phonenumber'])) {
                    $mobile = $decryptData['phonenumber'];

                }
                if (!$mobile && !empty($decryptData['purephonenumber'])) {
                    $mobile = $decryptData['purephonenumber'];
                }
                if ($mobile) {
                    $UserInfo = \app\common\model\User::where(['mobile' => $mobile])->find();
                    if ($UserInfo) {
                        $UserOauthInfo = UserOauth::where([
                            'openid'  => $decryptData['openid'],
                            'user_id' => ['neq', 0]
                        ])->where('platform', 'wxMiniProgram')->where('provider', 'Wechat')->find();
                        if (!$UserOauthInfo) {
                            $inser['user_id']  = $UserInfo['id'];
                            $inser['platform'] = 'wxMiniProgram';
                            $inser['provider'] = 'Wechat';
                            $inser['openid']   = $decryptData['openid'];
                            UserOauth::create($inser);
                        }
                    }
                }
                $decryptData['headimgurl']  = $post['avatarurl'] ?? '';
                $decryptData['nickname']  = $post['nickname'] ?? '';
//                $decryptData['sex']         = $decryptData['gender'] ?? '';
                $decryptData['session_key'] = $decryptSession['session_key'];
                $decryptData['parent_id'] = $post['share_id']??0;
                return $this->oauthLoginOrRegisterOrBindOrRefresh($post['event'], $decryptData, 'wxMiniProgram',
                    'Wechat');
            } catch (\Exception $e) {
                $this->error($e->getMessage());
            }
        });

        if ($token) {
            $this->success(__('Logged in successful'), ['token' => $token]);
        } else {
            $this->error($this->auth->getError());
        }
    }


    /**
     * 微信小程序登录
     *
     * @param  string  $code  加密code
     */
    public function wxMiniProgramPhone()
    {
        $user = $this->auth->getUser();

        $post = $this->request->post();
        $flag = false;

        if ($post['type'] == 'get') {
            if ($this->auth->mobile) {
                $this->success("绑定成功", [
                    'phone' => $this->auth->mobile
                ]);
            }
            $flag = true;
        }
        $decryptSession  = \think\Cache::get($post['session_id']);
        $wechat          = new Wechat('wxMiniProgram');
        $decryptUserInfo = $wechat->decryptData($decryptSession['session_key'], $post['iv'], $post['encryptedData']);

        $phone = $decryptUserInfo['purePhoneNumber'];

        if (empty($phone)) {
            $this->error('获取手机号授权失败');
        }
        if ($flag) {
            if (!\app\common\model\User::where('mobile', $phone)->where('id', '<>', $user->id)->find()) {
                $verification         = $user->verification;
                $verification->mobile = 1;
                $user->verification   = $verification;
                $user->mobile         = $phone;
                $user->save();
            }
        }
        if ($post['type'] == 'bind') {
            // 绑定手机号
            if (\app\common\model\User::where('mobile', $phone)->where('id', '<>', $user->id)->find()) {
                $this->error('手机号已存在');
            }

            $verification         = $user->verification;
            $verification->mobile = 1;
            $user->verification   = $verification;
            $user->mobile         = $phone;
            $user->save();
        }

        $this->success("绑定成功", [
            'phone' => $phone
        ]);
    }

    /**
     * 第三方登录或自动注册
     *
     * @param  array  $decryptData  解密参数
     * @param  string  $platform  平台名称
     * @param  string  $provider  厂商名称
     * @param  int  $keeptime  有效时长
     * @param  boolean  $refresh  刷新头像和昵称
     */
    private function oauthLoginOrRegisterOrBindOrRefresh($event, $decryptData, $platform, $provider, $keeptime = 0)
    {
        $oauthData = $decryptData;
        $oauthData = array_merge($oauthData, [
            'provider' => $provider,
            'platform' => $platform,

        ]);
        if ($platform === 'wxMiniProgram' || $platform === 'App') {
            $oauthData['expire_in']  = 7200;
            $oauthData['expiretime'] = time() + 7200;
        }
        $userOauth = UserOauth::where(['openid' => $decryptData['openid'], 'user_id' => ['neq', 0]])->where('platform',
            $platform)->where('provider', $provider)->lock(true)->find();
        switch ($event) {
            case 'login':               // 登录(自动注册)
                if (!$userOauth) {      // 没有找到第三方登录信息 创建新用户
                    //默认创建新用户
                    $user_id                 = 0;
                    $createNewUser           = true;
                    $oauthData['logintime']  = time();
                    $oauthData['logincount'] = 1;
                    // 判断是否有unionid 并且已存在oauth数据中
                    if (isset($oauthData['unionid'])) {
                        //存在同厂商信息，添加oauthData数据，合并用户
                        $userUnionOauth = UserOauth::get([
                            'unionid'  => $oauthData['unionid'],
                            'provider' => $provider,
                            'user_id'  => ['neq', 0]
                        ]);
                        if ($userUnionOauth) {
                            $existUser = $this->auth->direct($userUnionOauth->user_id);
                            if ($existUser) {
                                $createNewUser = false;
                            }
                        }
                    }

                    // 创建空用户
                    if ($createNewUser) {
                        $username           = Random::alnum(20);
                        $password           = '';
                        $domain             = request()->host();
                        $extend             = $this->getUserDefaultFields();
                        $extend['nickname'] = $oauthData['nickname'] ?? '';
                        $extend['avatar']   = $oauthData['headimgurl'] ?? '';
                        $extend['parent_id'] = $oauthData['share_id']??0;
                        if($extend['parent_id']){
                            $salesperson_id = \addons\groupon\model\User::where(['id'=>$extend['parent_id']])->value('salesperson_id');
                            if($salesperson_id){
                                $extend['salesperson_id'] = $salesperson_id;
                            }
                        }
                        $this->auth->register($username, $password, $username.'@'.$domain, '', $extend, $keeptime);
                        if (empty($oauthData['nickname'])) {
                            $this->auth->getUser()->save(['nickname' => $extend['nickname'].$this->auth->getUser()->id]);
                        }
                    }
                    $oauthData['user_id']    = $this->auth->getUser()->id;
                    $oauthData['createtime'] = time();
                    UserOauth::strict(false)->insert($oauthData);
                } else {
                    // 找到第三方登录信息，直接登录
                    $user_id = $userOauth->user_id;
                    if ($this->auth->direct($user_id) && $this->auth->getUser()) {       // 获取到用户
                        $oauthData['logincount'] = $userOauth->logincount + 1;
                        $oauthData['logintime']  = time();
                        $userOauth->allowField(true)->save($oauthData);
                    } else {         // 用户已被删除 重新执行登录
                        // throw new \Exception('此用户已删除');
                        $userOauth->delete();
                        $this->oauthLoginOrRegisterOrBindOrRefresh($event, $decryptData, $platform, $provider);
                    }
                }
                break;
            case 'refresh':
                if (!$userOauth) {
                    throw new \Exception('未找到第三方授权账户');
                }
                if (!empty($oauthData['nickname'])) {
                    $refreshFields['nickname'] = $oauthData['nickname'];
                }
                if (!empty($oauthData['headimgurl'])) {
                    $refreshFields['avatar'] = $oauthData['headimgurl'];
                }
                $this->auth->getUser()->save($refreshFields);
                $userOauth->allowField(true)->save($oauthData);
                break;
            case 'bind':
                if (!$this->auth->getUser()) {
                    throw new \Exception('请先登录');
                }

                $oauthData['user_id'] = $this->auth->getUser()->id;

                if ($userOauth) {
                    if ($userOauth['user_id'] != 0 && $userOauth['user_id'] != $this->auth->getUser()->id && UserModel::get($userOauth['user_id'])) {
                        throw new \Exception('该账号已被其他用户绑定');
                    }
                    $oauthData['id'] = $userOauth->id;
                    $userOauth->strict(false)->update($oauthData);
                } else {
                    $oauthData['logincount'] = 1;
                    $oauthData['logintime']  = time();
                    $oauthData['createtime'] = time();
                    UserOauth::strict(false)->insert($oauthData);
                }
                break;
        }
        if ($this->auth->getUser()) {
            return $this->auth->getToken();
        }
        return false;
    }


    /**
     * 手机验证码登录
     *
     * @param  string  $mobile  手机号
     * @param  string  $code  验证码
     */
    public function mobileLogin()
    {
        $mobile = $this->request->post('mobile');
        $code   = $this->request->post('code');
        if (!$mobile || !$code) {
            $this->error(__('Invalid parameters'));
        }
        if (!Validate::regex($mobile, "^1\d{10}$")) {
            $this->error(__('Mobile is incorrect'));
        }
        if (!Sms::check($mobile, $code, 'mobilelogin')) {
            $this->error(__('Captcha is incorrect'));
        }
        $user = \app\common\model\User::getByMobile($mobile);
        if ($user) {
            if ($user->status != 'normal') {
                $this->error(__('Account is locked'));
            }
            //如果已经有账号则直接登录
            $ret = $this->auth->direct($user->id);
        }
        if ($ret) {
            Sms::flush($mobile, 'mobilelogin');
            $data = ['userinfo' => $this->auth->getUserinfo()];
            $this->success(__('Logged in successful'), $data);
        } else {
            $this->error($this->auth->getError());
        }
    }

    /**
     * 注册会员
     *
     * @param  string  $username  用户名
     * @param  string  $password  密码
     * @param  string  $email  邮箱
     * @param  string  $mobile  手机号
     * @param  string  $code  验证码
     */
    public function register()
    {
        $username = $this->request->post('mobile');
        $password = $this->request->post('password');
        $email    = $this->request->post('mobile').'@'.request()->host();

        $mobile = $this->request->post('mobile');
        $code   = $this->request->post('code');
        if (!$password) {
            $this->error(__('请填写密码')); //TODO:密码规则校验
        }
        if (strlen($password) < 6 || strlen($password) > 16) {
            $this->error(__('密码长度 6-16 位')); //TODO:密码规则校验
        }
        if ($email && !Validate::is($email, "email")) {
            $this->error(__('邮箱填写错误'));
        }
        if ($mobile && !Validate::regex($mobile, "^1\d{10}$")) {
            $this->error(__('手机号填写错误'));
        }
        $ret = Sms::check($mobile, $code, 'register');
        if (!$ret) {
            $this->error(__('Captcha is incorrect'));
        }
        $extend = $this->getUserDefaultFields();
        $ret    = $this->auth->register($username, $password, $email, $mobile, $extend);
        if ($ret) {
            $user           = $this->auth->getUser();
            $user->nickname = $user->nickname.$user->id;
            $user->save();
            $data = ['userinfo' => $this->auth->getUserinfo()];
            $this->success(__('注册成功'), $data);
        } else {
            $this->error($this->auth->getError());
        }
    }

    /**
     * 注销登录
     */
    public function logout()
    {
        $this->auth->logout();
        $this->success(__('Logout successful'));
    }

    /**
     * 修改会员个人信息
     *
     * @param  string  $avatar  头像地址
     * @param  string  $username  用户名
     * @param  string  $nickname  昵称
     * @param  string  $birthday  生日
     * @param  string  $bio  个人简介
     */
    public function profile()
    {
        $user     = $this->auth->getUser();
        $username = $this->request->post('username');
        $nickname = $this->request->post('nickname');
        $bio      = $this->request->post('bio', '');
        $birthday = $this->request->post('birthday');
        $avatar   = $this->request->post('avatar', '', 'trim,strip_tags,htmlspecialchars');
        if ($username) {
            $exists = \app\common\model\User::where('username', $username)->where('id', '<>', $this->auth->id)->find();
            if ($exists) {
                $this->error(__('Username already exists'));
            }
            $user->username = $username;
        }
        $user->nickname = $nickname;
        $user->bio      = $bio;
        $user->birthday = $birthday;
        $user->avatar   = $avatar;
        $user->save();
        $this->success();
    }

    /**
     * 修改邮箱
     *
     * @param  string  $email  邮箱
     * @param  string  $captcha  验证码
     */
    public function changeemail()
    {
        $user    = $this->auth->getUser();
        $email   = $this->request->post('email');
        $captcha = $this->request->request('captcha');
        if (!$email || !$captcha) {
            $this->error(__('Invalid parameters'));
        }
        if (!Validate::is($email, "email")) {
            $this->error(__('Email is incorrect'));
        }
        if (\app\common\model\User::where('email', $email)->where('id', '<>', $user->id)->find()) {
            $this->error(__('Email already exists'));
        }
        $result = Ems::check($email, $captcha, 'changeemail');
        if (!$result) {
            $this->error(__('Captcha is incorrect'));
        }
        $verification        = $user->verification;
        $verification->email = 1;
        $user->verification  = $verification;
        $user->email         = $email;
        $user->save();

        Ems::flush($email, 'changeemail');
        $this->success();
    }

    /**
     * 修改手机号
     *
     * @param  string  $mobile  手机号
     * @param  string  $captcha  验证码
     */
    public function changemobile()
    {
        $user    = $this->auth->getUser();
        $mobile  = $this->request->post('mobile');
        $captcha = $this->request->post('captcha');
        if (!$mobile || !$captcha) {
            $this->error(__('Invalid parameters'));
        }
        if (!Validate::regex($mobile, "^1\d{10}$")) {
            $this->error(__('Mobile is incorrect'));
        }
        if (\app\common\model\User::where('mobile', $mobile)->where('id', '<>', $user->id)->find()) {
            $this->error(__('Mobile already exists'));
        }
        $result = Sms::check($mobile, $captcha, 'changemobile');
        if (!$result) {
            $this->error(__('Captcha is incorrect'));
        }
        $verification         = $user->verification;
        $verification->mobile = 1;
        $user->verification   = $verification;
        $user->mobile         = $mobile;
        $user->save();

        Sms::flush($mobile, 'changemobile');
        $this->success();
    }


    /**
     * 重置密码
     *
     * @param  string  $mobile  手机号
     * @param  string  $newpassword  新密码
     * @param  string  $captcha  验证码
     */
    public function resetpwd()
    {
        $type        = $this->request->post("type", 'mobile');
        $mobile      = $this->request->post("mobile");
        $email       = $this->request->post("email");
        $newpassword = $this->request->post("newpassword");
        $captcha     = $this->request->post("captcha");
        if (!$newpassword || !$captcha) {
            $this->error(__('Invalid parameters'));
        }
        if (strlen($newpassword) < 6 || strlen($newpassword) > 16) {
            $this->error(__('密码长度 6-16 位')); //TODO:密码规则校验
        }
        if ($type == 'mobile') {
            if (!Validate::regex($mobile, "^1\d{10}$")) {
                $this->error(__('Mobile is incorrect'));
            }
            $user = \app\common\model\User::getByMobile($mobile);
            if (!$user) {
                $this->error(__('User not found'));
            }
            $ret = Sms::check($mobile, $captcha, 'resetpwd');
            if (!$ret) {
                $this->error(__('Captcha is incorrect'));
            }
            Sms::flush($mobile, 'resetpwd');
        } else {
            if (!Validate::is($email, "email")) {
                $this->error(__('Email is incorrect'));
            }
            $user = \app\common\model\User::getByEmail($email);
            if (!$user) {
                $this->error(__('User not found'));
            }
            $ret = Ems::check($email, $captcha, 'resetpwd');
            if (!$ret) {
                $this->error(__('Captcha is incorrect'));
            }
            Ems::flush($email, 'resetpwd');
        }
        //模拟一次登录
        $this->auth->direct($user->id);
        $ret = $this->auth->changepwd($newpassword, '', true);
        if ($ret) {
            $this->success(__('Reset password successful'));
        } else {
            $this->error($this->auth->getError());
        }
    }


    public function changepwd()
    {
        $user = $this->auth->getUser();

        $oldpassword = $this->request->post("oldpassword");
        $newpassword = $this->request->post("newpassword");

        if (!$newpassword || !$oldpassword) {
            $this->error(__('Invalid parameters'));
        }
        if (strlen($newpassword) < 6 || strlen($newpassword) > 16) {
            $this->error(__('密码长度 6-16 位')); //TODO:密码规则校验
        }

        $ret = $this->auth->changepwd($newpassword, $oldpassword);

        if ($ret) {
            $this->auth->direct($user->id);
            $data = ['userinfo' => $this->auth->getUserinfo()];

            $this->success(__('Change password successful'), $data);
        } else {
            $this->error($this->auth->getError());
        }
    }

    private function getUserDefaultFields()
    {
        $userConfig = json_decode(\addons\groupon\model\Config::get(['name' => 'user'])->value, true);
        return $userConfig;
    }



    public function trad_id($user_id){
        $rand     = $user_id < 9999 ? mt_rand(100000, 99999999) : mt_rand(100, 99999);
        $order_sn = date('Yhis').$rand;

        $id = str_pad($user_id, (24 - strlen($order_sn)), '0', STR_PAD_BOTH);

        return $order_sn.$id;
    }

    /**
     *申请成为业务员
     * @return void
     *
     */
    public function salespersonApply(){
        $params = $this->request->post();
        $validate = new Apply();
        $validate->scene("salespersonApply")->check($params);
        $model = new UserSalespersonApplyModel();
        $model->apply($params);
        $this->success('ok');
    }
}
